package hku.cs.lunuo.views;

import hku.cs.constant.DirAndFileConstant;
import hku.cs.lunuo.LunuoPlugin;
import hku.cs.lunuo.launch.LunuoLaunchConstant;
import hku.cs.lunuo.page.PreferenceConstant;
import hku.cs.lunuo.util.MD5;
import hku.cs.rank.ComputeRank;
import hku.cs.tools.DirTools;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class RankView extends ViewPart {
	private IJavaProject javaProject;
	private String rankAlgName="tarantula";
	private String currentRank = "";
	private ComboViewer algViewer;

	public ComboViewer getAlgViewer() {
		return algViewer;
	}

	public void setAlgViewer(ComboViewer algViewer) {
		this.algViewer = algViewer;
	}

	public static final String VIEW_ID = "hku.cs.lunuo.view.rankView";
//	private Label label;
	private TableViewer tableViewer;
	private TestContentProvider testContentProvider = new TestContentProvider();
	private CheckboxTreeViewer treeViewer;

	private final Image fLunuoIcon = createImage("sample.gif");
	
	public String getCurrentRank() {
		return currentRank;
	}

	public void setCurrentRank(String currentRank) {
		this.currentRank = currentRank;
	}

//	public Label getLabel() {
//		return label;
//	}
//
//	public void setLabel(Label label) {
//		this.label = label;
//	}

	public String getRankAlgName() {
		return rankAlgName;
	}

	public void setRankAlgName(String rankAlgName) {
		this.rankAlgName = rankAlgName;
	}

	public IJavaProject getJavaProject() {
		return javaProject;
	}

	public void setJavaProject(IJavaProject javaProject) {
		this.javaProject = javaProject;
	}

	private List<Rank> ranks = new ArrayList<Rank>();

	public List<Rank> getRanks() {
		return ranks;
	}

	public void setRanks(List<Rank> ranks) {
		this.ranks = ranks;
	}

	public TableViewer getTableViewer() {
		return tableViewer;
	}

	public void setTableViewer(TableViewer tableViewer) {
		this.tableViewer = tableViewer;
	}

	public CheckboxTreeViewer getTreeViewer() {
		return treeViewer;
	}

	public void setTreeViewer(CheckboxTreeViewer treeViewer) {
		this.treeViewer = treeViewer;
	}

	public RankView() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void createPartControl(Composite parent) {
		
		Composite composite = new Composite(parent, SWT.NULL);
		
		
		GridLayout l = new GridLayout();
		l.numColumns=2;
		l.makeColumnsEqualWidth = false;
		
		composite.setLayout(l);
		
		
		
//		Group g = new Group(composite, SWT.NONE);
		Composite incomp = new Composite(composite, SWT.NONE);
		l = new GridLayout();
		l.numColumns = 2;
		incomp.setLayout(l);
		incomp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
		
		Label label = new Label(incomp, SWT.WRAP);
		label.setText("Rank Algorithm");
		label.setLayoutData(new GridData(GridData.BEGINNING));
		
		algViewer = new ComboViewer(incomp, SWT.DROP_DOWN | SWT.READ_ONLY);
		algViewer.getCombo().setLayoutData(
				new GridData(GridData.FILL_HORIZONTAL));

		algViewer.setContentProvider(new ArrayContentProvider());
		algViewer.setLabelProvider(new LabelProvider());
		algViewer.setInput(LunuoLaunchConstant.ALGS);
		algViewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection selection = (IStructuredSelection) algViewer
				.getSelection();
				rankAlgName = selection.getFirstElement().toString();
			}
		});
		algViewer.setSelection(new StructuredSelection(rankAlgName));
		
//		Button changeAlg = new Button(incomp, SWT.PUSH);
//		changeAlg.setImage(fLunuoIcon);
//		changeAlg.addMouseListener(new MouseListener(){
//
//			@Override
//			public void mouseDoubleClick(MouseEvent e) {
//				// TODO Auto-generated method stub
//				
//			}
//
//			@Override
//			public void mouseDown(MouseEvent e) {
//				// TODO Auto-generated method stub
//				
//			}
//
//			@Override
//			public void mouseUp(MouseEvent e) {
//				// TODO Auto-generated method stub
//				
//			}
//			
//		});
		
		treeViewer = new CheckboxTreeViewer(incomp,
				SWT.SINGLE | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.BORDER
						| SWT.V_SCROLL);
		
		GridData gridData1 = new GridData();
		gridData1.horizontalAlignment = GridData.FILL;
		gridData1.grabExcessVerticalSpace = true;
		gridData1.verticalAlignment= GridData.FILL;
		gridData1.widthHint = 300;
		gridData1.horizontalSpan=2;
		treeViewer.getTree().setLayoutData(gridData1);
		
		treeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);

		treeViewer.setLabelProvider(new TestLabelProvider());
		treeViewer.setContentProvider(testContentProvider);
		
		treeViewer.setInput(new ArrayList<Ltest>(0));
//		updateTreeCheck(testConstruct);
		treeViewer.addCheckStateListener(new ICheckStateListener() {

			@Override
			public void checkStateChanged(CheckStateChangedEvent event) {				
				
				Ltest selectTest = (Ltest) event.getElement();
				boolean isChecked = event.getChecked();

				if(selectTest instanceof LtestCase){
					treeViewer.setSubtreeChecked(selectTest, isChecked);

						
				}else if(selectTest instanceof LtestMethod){
					Object p = testContentProvider.getParent(selectTest);
					if(isChecked){
						boolean allChecked = true;
						Object[] tts = testContentProvider.getChildren(p);
						for(Object test : tts)
							if(treeViewer.getChecked(test) == false)
								allChecked = false;
						if(allChecked){
							treeViewer.setChecked(p, true);
						}
					}else if(treeViewer.getChecked(p)){
						treeViewer.setChecked(p, false);
					}
					
				}

			}

		});
		
		treeViewer.addDoubleClickListener(new IDoubleClickListener(){

			@Override
			public void doubleClick(DoubleClickEvent event) {
				if(event.getSelection() instanceof IStructuredSelection) {
					IStructuredSelection selection = (IStructuredSelection)event.getSelection();
					Ltest test = (Ltest)selection.getFirstElement();
					fillTableViewer(test);
				}
								
			}

			

			
		});
		
		// This is new code
		// First we create a menu Manager
		MenuManager menuManager = new MenuManager();
		Menu menu = menuManager.createContextMenu(treeViewer.getTree());
		// Set the MenuManager
		treeViewer.getTree().setMenu(menu);
		getSite().registerContextMenu(menuManager, treeViewer);
		// Make the selection available
		getSite().setSelectionProvider(treeViewer);


		tableViewer = new TableViewer(composite, SWT.SINGLE | SWT.FULL_SELECTION
				| SWT.H_SCROLL | SWT.BORDER | SWT.V_SCROLL);
		Table table = tableViewer.getTable();

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		String[] columnNames = new String[] { "", "index", "rank",
				"suspicious", "line", "class" };
		int[] columnWidths = new int[] { 20, 50, 50, 100, 50, 200 };
		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		table.addSelectionListener(new SelectionAdapter() {
			public void widgetDefaultSelected(SelectionEvent e) {
				handleDefaultSelected();
			}
		});
		
		GridData gridData2 = new GridData();
		gridData2.horizontalAlignment = GridData.FILL;
//		gridData1.grabExcessHorizontalSpace = true;
		gridData2.grabExcessVerticalSpace = true;
		gridData2.verticalAlignment= GridData.FILL;
		gridData2.horizontalAlignment= GridData.FILL;
		gridData2.grabExcessHorizontalSpace = true;
		table.setLayoutData(gridData2);

		tableViewer.setLabelProvider(new RankLableProvider());
		tableViewer.setContentProvider(new ArrayContentProvider());
		tableViewer.setInput(new ArrayList<Rank>(0));

	}
	
	private Ltest findTopParent(Ltest test) {
		Ltest t = test;
		while(t.getParent()!=null)
			t = t.getParent();
		
		return t;
	}
	
	public void fillTableViewer(Ltest test){
		if(test instanceof LtestCase){
			List<Ltest> ts = test.getChildren();
			List<String> args = new ArrayList<String>();
			for(Ltest t : ts){
				if(treeViewer.getChecked(t))
					args.add(t.getName());							
			}
			if(args.size()==0)
				return;
			Ltest top = findTopParent(test);
			StringBuffer sb = new StringBuffer();
			sb.append(LunuoPlugin.METADIR);
			
			sb.append(getJavaProject().getElementName());
			sb.append(DirTools.SEPERATOR);
			sb.append(top.getName());
			sb.append(DirTools.SEPERATOR);
			sb.append(test.getName());
			sb.append(DirTools.SEPERATOR);
			if(rankAlgName==null){
				rankAlgName = LunuoPlugin.getDefault().
					getPreferenceStore().getString(PreferenceConstant.ALG_KEY);
			}
			if(rankAlgName.equals(""))
				rankAlgName="tarantula";
			
			String sx = sb.toString();
			
			sb.append(DirAndFileConstant.RANK);
			sb.append(DirAndFileConstant.LB);
			sb.append(rankAlgName);
			sb.append(DirAndFileConstant.RB);
			sb.append(DirAndFileConstant.SP);
			
			StringBuffer sbu = new StringBuffer();
			for(String s : args){
				sbu.append(s);
			}
		
			String ssnu = MD5.getMD5(sbu.toString().getBytes());
			sb.append(ssnu);

			sb.append(DirAndFileConstant.FILEEXTENTION);

			ranks.clear();
			if(!readRank(sb.toString())){
				new ComputeRank(rankAlgName).doDir(new File(sx), args, ssnu);
//			String fileName = DoNewRank(ts);
				readRank(sb.toString());
			}
			
			tableViewer.setInput(ranks);
			
//			label.setText(rankAlgName);
		}
	}
	
	private Image createImage(String path) {
		return LunuoPlugin.getDefault().getImageDescriptor(path).createImage();
	}

	private boolean readRank(String xmlFileName) {
		if(!new File(xmlFileName).exists())
			return false;
		this.setCurrentRank(xmlFileName);
		SAXBuilder sb = new SAXBuilder();
		File f = new File(xmlFileName);
		try {
			Document xmlDoc = sb.build(f);
			Element xmlRoot = xmlDoc.getRootElement();
			IProject project = ResourcesPlugin.getWorkspace().getRoot()
					.getProject("try");
			Iterator xmlStmtIt = xmlRoot.getChildren("statement").iterator();
			while (xmlStmtIt.hasNext()) {
				Element xmlStmt = (Element) xmlStmtIt.next();
				int index = Integer
						.parseInt(xmlStmt.getAttributeValue("index"));
				String klass = xmlStmt.getAttributeValue("class");
				int line = Integer.parseInt(xmlStmt.getAttributeValue("line"));

				int rank = Integer.parseInt(xmlStmt.getChild("rank").getText());
				float sus = Float.parseFloat(xmlStmt.getChild("suspiciousness")
						.getText());

				ranks.add(new Rank(index, rank, sus, line, klass, project));
			}
		return true;
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

	}

	

	protected void handleDefaultSelected() {
		IStructuredSelection s = (IStructuredSelection) tableViewer
				.getSelection();
		Object firstElement = s.getFirstElement();
		if (firstElement != null)
			openTest((Rank) firstElement);
	}

	private void openTest(Rank result) {
		try {
			IType type = JavaCore.create(getJavaProject().getProject()).findType(
					result.getKlass());
			ITextEditor editor = (ITextEditor) JavaUI.openInEditor(type);

			IDocumentProvider provider = editor.getDocumentProvider();
			IDocument document = provider.getDocument(editor.getEditorInput());
			try {
				int start = document.getLineOffset(result.getLine() - 1);
				
				editor.selectAndReveal(start, 0);
				IWorkbenchPage page = editor.getSite().getPage();
				page.activate(editor);

			} catch (org.eclipse.jface.text.BadLocationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} catch (CoreException e) {
			// TODO
		}
	}

	@Override
	public void setFocus() {
		tableViewer.getControl().setFocus();
	}

	public TableViewer getViewer() {
		return tableViewer;
	}

	@Override
	public void dispose() {
		fLunuoIcon.dispose();
		super.dispose();
	}

}
